package eclipse_sync_plugin;
import java.io.File;
import java.io.FileWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.swt.custom.CaretEvent;
import org.eclipse.swt.custom.CaretListener;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.ide.FileStoreEditorInput;

public class CursorChangeListener implements IPartListener2 {
	private ILog logger;
	// 使用Path对象存储状态文件路径
    private static final Path STATE_FILE_PATH = Paths.get(
        System.getProperty("user.home"),
        ".eclipse-cursor-sync-plugin",
        "eclipse_editor_state.json"
    );
    // 状态文件对象复用
    private static final File STATE_FILE = STATE_FILE_PATH.toFile();
    
    // 用于跟踪每个编辑器的光标监听器
    private final Map<IEditorPart, CaretListener> editorListeners = new ConcurrentHashMap<>();
    
    // 节流控制
    private static final long THROTTLE_INTERVAL_MS = 300; // 500毫秒的节流间隔
    private final AtomicLong lastWriteTime = new AtomicLong(0);
    private String pendingJson = null;
    private Thread writeThread = null;
    
    public CursorChangeListener() {
        try {
            this.logger = Platform.getLog(Platform.getBundle("eclipse-sync-plugin"));
        } catch (Exception e) {
            System.err.println("初始化日志失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    @Override
    public void partActivated(IWorkbenchPartReference partRef) {
        IEditorPart editor = partRef.getPage().getActiveEditor();
        if (editor != null) {
            logger.log(new Status(IStatus.INFO, "eclipse-sync-plugin", "编辑器已激活: " + editor.getTitle()));
            
            // 检查是否已经为该编辑器添加了监听器
            if (!editorListeners.containsKey(editor)) {
                // 尝试获取ITextViewer
                ITextViewer viewer = null;
                if (editor instanceof AbstractTextEditor) {
                    viewer = (ITextViewer) ((AbstractTextEditor) editor).getAdapter(ITextViewer.class);
                } else if (editor.getClass().getName().contains("XMLMultiPageEditorPart")) {
                    // XML编辑器的特殊处理
                    viewer = (TextViewer) editor.getAdapter(ITextViewer.class);
                } else {
                    // 尝试直接从编辑器获取ITextViewer
                    viewer = (ITextViewer) editor.getAdapter(ITextViewer.class);
                }
                
                if (viewer != null) {
                    CaretListener caretListener = new CaretListener() {
                        @Override
                        public void caretMoved(CaretEvent event) {
                            logCursorPosition(editor, event.caretOffset);
                        }
                    };
                    viewer.getTextWidget().addCaretListener(caretListener);
                    editorListeners.put(editor, caretListener);
                    
                    logger.log(new Status(IStatus.INFO, "eclipse-sync-plugin", "已为编辑器添加光标监听器: " + editor.getTitle()));
                } else {
                    logger.log(new Status(IStatus.WARNING, "eclipse-sync-plugin", "无法获取编辑器的文本视图: " + editor.getTitle()));
                }
            }
        }
    }
    
    @Override
    public void partClosed(IWorkbenchPartReference partRef) {
        // 获取被关闭的部分
        Object part = partRef.getPart(true);
        // 检查是否是编辑器
        if (part instanceof IEditorPart) {
            IEditorPart editor = (IEditorPart) part;
            // 移除该编辑器的光标监听器
            CaretListener listener = editorListeners.remove(editor);
            if (listener != null) {
                ITextViewer viewer = null;
                if (editor instanceof AbstractTextEditor) {
                    viewer = (ITextViewer) ((AbstractTextEditor) editor).getAdapter(ITextViewer.class);
                } else {
                    viewer = (ITextViewer) editor.getAdapter(ITextViewer.class);
                }
                if (viewer instanceof TextViewer) {
                    ((TextViewer) viewer).getTextWidget().removeCaretListener(listener);
                    logger.log(new Status(IStatus.INFO, "eclipse-sync-plugin", "已移除编辑器的光标监听器: " + editor.getTitle()));
                }
            }
        }
    }
    
    private void logCursorPosition(IEditorPart editor, int viewOffset) {
        try {
            // 获取文件路径
            IEditorInput input = editor.getEditorInput();
            Path fullPath;
            if (input instanceof FileEditorInput) {
                IFile file = ((FileEditorInput) input).getFile();
                fullPath = Path.of(file.getLocationURI());
            } else if (input instanceof FileStoreEditorInput) {
                fullPath = Path.of(((FileStoreEditorInput) input).getURI());
            } else {
                //打印实际类型
                logger.log(new Status(IStatus.WARNING, "eclipse-sync-plugin", 
                    "编辑器输入不是文件类型：" + input.getClass().getPackageName() + ":" + input.getClass().getName()));
                return;
            }

            // 获取ProjectionViewer
            TextViewer viewer = null;
            if (editor instanceof AbstractTextEditor) {
                viewer = (TextViewer) ((AbstractTextEditor) editor).getAdapter(ITextViewer.class);
            } else {
                // XML编辑器的特殊处理
                viewer = (TextViewer) editor.getAdapter(ITextViewer.class);
            }

            if (viewer == null) {
                logger.log(new Status(IStatus.WARNING, "eclipse-sync-plugin", "无法获取编辑器的文本视图"));
                return;
            }

            int line, column;
            if (!(viewer instanceof ProjectionViewer)) {
                // 回退方案：直接用StyledText获取行号和列号
                org.eclipse.swt.custom.StyledText styledText = viewer.getTextWidget();
                int caretOffset = styledText.getCaretOffset();
                line = styledText.getLineAtOffset(caretOffset) + 1; // 行号从1开始
                column = caretOffset - styledText.getOffsetAtLine(line - 1) + 1; // 列号从1开始
            } else {
                ProjectionViewer projectionViewer = (ProjectionViewer) viewer;
                IDocument doc = projectionViewer.getDocument();
                org.eclipse.swt.custom.StyledText styledText = projectionViewer.getTextWidget();
                int caretOffset = styledText.getCaretOffset();
                int modelOffset = projectionViewer.widgetOffset2ModelOffset(caretOffset);
                if (modelOffset < 0) modelOffset = 0;
                line = doc.getLineOfOffset(modelOffset) + 1;
                column = modelOffset - doc.getLineOffset(line - 1) + 1;
            }

            // 生成ISO8601时间戳
            String timestamp = DateTimeFormatter.ISO_INSTANT.format(Instant.now());

            // 构建JSON数据
            String json = String.format(
                "{\n" +
                "  \"file_path\": \"%s\",\n" +
                "  \"line_number\": %d,\n" +
                "  \"column\": %d,\n" +
                "  \"timestamp\": \"%s\"\n" +
                "}",
                fullPath.toString().replace("\\", "\\\\"),
                line,
                column,
                timestamp
            );

            // 使用节流机制写入文件
            scheduleWrite(json);
            
        } catch (Exception e) {
            logger.log(new Status(IStatus.ERROR, "eclipse-sync-plugin",
                "记录光标位置时发生错误: " + e.getMessage(), e));
        }
    }
    
    private synchronized void scheduleWrite(String json) {
        pendingJson = json;
        long currentTime = System.currentTimeMillis();
        long lastWrite = lastWriteTime.get();
        
        if (currentTime - lastWrite >= THROTTLE_INTERVAL_MS) {
            // 如果距离上次写入已经超过节流间隔，立即写入
            writePendingJson();
        } else if (writeThread == null || !writeThread.isAlive()) {
            // 否则，启动一个延迟写入线程
            
        }
    }
    private synchronized void writePendingJson() {
        if (pendingJson != null) {
            try (FileWriter writer = new FileWriter(STATE_FILE, false)) {
                writer.write(pendingJson);
                lastWriteTime.set(System.currentTimeMillis());
                
                // 直接输出JSON内容到日志
                logger.log(new Status(IStatus.INFO, "eclipse-sync-plugin", 
                    "已记录光标位置: " + pendingJson));
                
                pendingJson = null;
            } catch (Exception e) {
                logger.log(new Status(IStatus.ERROR, "eclipse-sync-plugin",
                    "写入状态文件失败: " + e.getMessage(), e));
            }
        }
    }
    
    // 其他必要方法（空实现）
    @Override public void partOpened(IWorkbenchPartReference partRef) {}
    @Override public void partDeactivated(IWorkbenchPartReference partRef) {}
    @Override public void partBroughtToTop(IWorkbenchPartReference partRef) {}
    @Override public void partHidden(IWorkbenchPartReference partRef) {}
    @Override public void partVisible(IWorkbenchPartReference partRef) {}
    @Override public void partInputChanged(IWorkbenchPartReference partRef) {}
    
    /**
     * 清理所有编辑器监听器
     */
    public void cleanupAllListeners() {
        try {
            // 遍历所有编辑器监听器并移除
            for (Map.Entry<IEditorPart, CaretListener> entry : editorListeners.entrySet()) {
                IEditorPart editor = entry.getKey();
                CaretListener listener = entry.getValue();
                
                if (editor instanceof AbstractTextEditor && listener != null) {
                    TextViewer viewer = (TextViewer) ((AbstractTextEditor) editor).getAdapter(ITextViewer.class);
                    if (viewer != null) {
                        viewer.getTextWidget().removeCaretListener(listener);
                        logger.log(new Status(IStatus.INFO, "eclipse-sync-plugin", 
                            "已清理编辑器监听器: " + editor.getTitle()));
                    }
                }
            }
            // 清空监听器Map
            editorListeners.clear();
            logger.log(new Status(IStatus.INFO, "eclipse-sync-plugin", "所有编辑器监听器已清理完成"));
        } catch (Exception e) {
            logger.log(new Status(IStatus.ERROR, "eclipse-sync-plugin", 
                "清理编辑器监听器时发生错误: " + e.getMessage(), e));
        }
    }
}